/* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <inttypes.h>
#include "ff.h"                // FatFs文件系统库
#include "diskio.h"            // FatFs磁盘I/O接口
#include "esp_vfs_fat.h"       // ESP-IDF FAT虚拟文件系统
#include "driver/sdmmc_defs.h" // SD/MMC驱动定义
#include "sdmmc_cmd.h"         // SD/MMC命令处理
#include "esp_idf_version.h"   // ESP-IDF版本检测
#include "esp_log.h"   // 日志打印
#include "sd_card.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "disk_main.h"
#include "usbd_core.h"
#include "usbd_msc.h"
#include "usb_public.h"
#include "wifi_main.h"
// 日志标签
static const char *TAG = "usb_msc_wireless";

#define MSC_WIFIDISK_CONFIG_SIZE (9 + MSC_DESCRIPTOR_LEN)
#define ESP_MSC_IN_EP            0x83
#define ESP_MSC_OUT_EP           0x04
#define MSC_MAX_MPS              64
// 挂载的SD卡对象指针和磁盘挂载路径
static sdmmc_card_t *mount_card = NULL;
//const char *disk_path = "/disk";


extern esp_err_t start_file_server(const char *base_path);
// USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0x00, 0x00, 0x00, USBD_VID, USBD_PID, 0x0200, 0x01),
//     USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
//     MSC_DESCRIPTOR_INIT(0x00, MSC_OUT_EP, MSC_IN_EP, MSC_MAX_MPS, 0x02),
static const uint8_t msc_wifi_disk_config_descriptor[] = {
    // 配置描述符
    USB_CONFIG_DESCRIPTOR_INIT(MSC_WIFIDISK_CONFIG_SIZE, 0x01, 0x01, USB_CONFIG_BUS_POWERED, 300),
    //(接口号、输出端点地址、输入端点地址、端点大小,字符串索引)
    MSC_DESCRIPTOR_INIT(0x00, ESP_MSC_OUT_EP, ESP_MSC_IN_EP, MSC_MAX_MPS, 0x02),
};

char *msc_wifi_disk_string_descriptors[] = {
    (char[]){ 0x09, 0x04 }, // 0: 支持的语言(英语0x0409)
    "MIDUO",                // 1: 制造商字符串
    "MSC WiFi Disk",        // 2: 产品名称
    "1234",//序列号
};
uint8_t *msc_wifi_disk_config_descriptor_callback(uint8_t speed)
{
    (void)speed;
    return msc_wifi_disk_config_descriptor;
}
__WEAK const char *msc_wifi_disk_string_descriptor_callback(uint8_t speed, uint8_t index)
{
    (void)speed;

    if (index >= (sizeof(msc_wifi_disk_string_descriptors) / sizeof(char *))) {
        return NULL;
    }
    return msc_wifi_disk_string_descriptors[index];
}
// USB 描述符配置结构体
const struct usb_descriptor msc_wifi_disk_cmsisdap_descriptor = {
    // 设备描述符回调函数（获取设备的基本信息，如VID、PID、设备类等）
    .device_descriptor_callback = usb_device_descriptor_callback_default,
    // 配置描述符回调函数（定义USB设备的配置、接口、端点等）
    .config_descriptor_callback = msc_wifi_disk_config_descriptor_callback,
    // 设备品质描述符回调函数（可选，用于返回设备品质描述符）
    .device_quality_descriptor_callback = usb_device_quality_descriptor_callback_default,
    // 其他速率配置描述符回调函数（用于USB高速/全速/低速兼容性描述）
    //.other_speed_descriptor_callback = esp_jtag_other_speed_config_descriptor_callback,
    // 字符串描述符回调函数（返回厂商、产品、序列号等字符串信息）
    .string_descriptor_callback = msc_wifi_disk_string_descriptor_callback,
    // BOS（Binary Device Object Store）描述符（用于USB 2.1+，支持扩展能力描述）
    .bos_descriptor = &bos_desc,
    // Microsoft OS 2.0描述符（用于Windows兼容性，如自动加载驱动）
    .msosv2_descriptor = &msosv2_desc,
};

static struct usbd_interface msc_wifi_disk_intf;
// 主应用程序入口
void msc_wifi_disk_start(uint8_t busid, uint32_t reg_base, const char *disk_path)
{


    /* 初始化文件存储 */
    //ESP_ERROR_CHECK(bsp_sdcard_mount());
    //vTaskDelay(100 / portTICK_PERIOD_MS); // 短暂延时

    /* 初始化Wi-Fi（使用menuconfig中的配置） */
    //app_wifi_main();
    wifi_init();
    /* 启动文件服务器 */
    start_file_server(disk_path);

    ESP_LOGI(TAG, "USB MSC init");
    usbd_desc_register(busid, &msc_wifi_disk_cmsisdap_descriptor);

    /*!< msc */
    usbd_add_interface(busid, usbd_msc_init_intf(busid, &msc_wifi_disk_intf, ESP_MSC_OUT_EP, ESP_MSC_IN_EP));
    extern void usbd_event_handler(uint8_t busid, uint8_t event);
    // usbd_event_handler在dap.main.c中定义
    usbd_initialize(busid, reg_base, usbd_event_handler);
    ESP_LOGI(TAG, "USB MSC init done");
}
/* 停止文件服务器的函数 */
extern esp_err_t stop_file_server(void);
/*stop msc_wifi_disk*/
void msc_wifi_disk_stop(uint8_t busid)
{
    stop_file_server();// 停止文件服务器
    usbd_deinitialize(busid);     // 反初始化USB设备
    usb_esp_jtag_serial_enable(); // 启用JTAG串口
}
    // 全局变量：物理驱动器号、磁盘块大小和弹出状态跟踪
static uint8_t s_pdrv = 0;
static int s_disk_block_size = 0;


uint16_t msc_wifi_disk_get_sector_size(void)
{
    uint16_t block_size;
    disk_ioctl(s_pdrv, GET_SECTOR_SIZE, &block_size);
    s_disk_block_size = block_size; // 保存块大小供后续使用
    return block_size;
}

uint32_t msc_wifi_disk_get_sector_count(void)
{
    uint32_t block_count;
    disk_ioctl(s_pdrv, GET_SECTOR_COUNT, &block_count);
    return block_count;
}
int msc_wifi_disk_read_sector(uint32_t start_sector, uint8_t *buff, uint32_t bufsize)
{
    // 计算需要读取的块数量
    const uint32_t block_count = bufsize / s_disk_block_size;
    //ESP_LOGE(TAG, "msc_wifi_disk_read_sector start_sector=%d, bufsize=%d, block_count=%d", start_sector, bufsize, block_count);

    // 从磁盘读取数据
    disk_read(s_pdrv, buff, start_sector, block_count);

    return 0; //
}
int msc_wifi_disk_write_sector(uint32_t start_sector, const uint8_t *buff, uint32_t bufsize)
{
    // 计算需要写入的块数量
    const uint32_t block_count = bufsize / s_disk_block_size;

    // 写入数据到磁盘
    disk_write(s_pdrv, buff, start_sector, block_count);

    return 0; // 返回实际写入的字节数
}
//     // 当收到READ10命令时调用
//     // 将磁盘数据复制到缓冲区（最多bufsize）并返回复制的字节数
//     int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void *buffer, uint32_t bufsize)
// {
//     ESP_LOGD(__func__, "LUN %u 读取: LBA=%" PRIu32 ", 偏移=%" PRIu32 ", 大小=%" PRIu32,
//              lun, lba, offset, bufsize);

//     if (lun >= LOGICAL_DISK_NUM)
//     {
//         ESP_LOGE(__func__, "无效的LUN编号 %u", lun);
//         return 0;
//     }

//     // 计算需要读取的块数量
//     const uint32_t block_count = bufsize / s_disk_block_size;

//     // 从磁盘读取数据
//     disk_read(s_pdrv, buffer, lba, block_count);

//     return block_count * s_disk_block_size; // 返回实际读取的字节数
// }

// // 当收到WRITE10命令时调用
// // 处理缓冲区中的数据到磁盘存储，并返回写入的字节数
// int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t *buffer, uint32_t bufsize)
// {
//     ESP_LOGD(__func__, "LUN %u 写入: LBA=%" PRIu32 ", 偏移=%" PRIu32 ", 大小=%" PRIu32,
//              lun, lba, offset, bufsize);
//     (void)offset; // 偏移参数未使用

//     if (lun >= LOGICAL_DISK_NUM)
//     {
//         ESP_LOGE(__func__, "无效的LUN编号 %u", lun);
//         return 0;
//     }

//     // 计算需要写入的块数量
//     const uint32_t block_count = bufsize / s_disk_block_size;

//     // 写入数据到磁盘
//     disk_write(s_pdrv, buffer, lba, block_count);

//     return block_count * s_disk_block_size; // 返回实际写入的字节数
// }
